/**
 * 20220304:[require] to [import]...jordia
 */
import {Object3D} from 'three';

const NULL=new Object3D();
let children={};
/**
 * 从导入的模型文件查询，记录和获取对象
 */
export default class Child{
    constructor(){
        console.error('do not instantiate this class,use static methods provided!');
    }

    /**
     * 销毁释放
     */
    static dispose(){
        for(let key in children){
            children[''+key+'']=null;
        }
        children={};
    }

    /**
     * 记录目标对象
     * @param key {String} 键值
     * @param location {Array} 自上而下的索引序列
     */
    static set(key,location){
        children[key]=location;
    }

    /**
     * 获取已经记录的对象（不更改对象父级时使用）
     * @param object {Object3D} 顶层父级
     * @param nameKey {String} 自上而下的索引序列
     * @returns {Object3D}
     */
    static get(object,nameKey){
        let name=children[nameKey];
        if(!name){
            console.warn('no child record was found,check the '+nameKey+'!');
            return null;
        }
        if(!(object.children)){
            console.warn('cannot get child from '+object+'!');
            return null;
        }
        let cd=(index,obj)=>{
            return obj.children[index];
        };
        let temp=object;
        for(let i of name){
            temp=cd(i,temp);
        }
        if(!temp)console.warn('no child was found!');
        return temp;
    }

    /**
     * 提取已经记录的对象（需要更改对象父级时使用，将用空物体占位）
     * @param object {Object3D} 顶层父级
     * @param nameKey {String} 自上而下的索引序列
     * @returns {Object3D}
     */
    static extract(object,nameKey){
        let name=children[nameKey];
        if(!name){
            console.warn('no child record was found,check the '+nameKey+'!');
            return null;
        }
        if(!(object.children)){
            console.warn('cannot get child from '+object+'!');
            return null;
        }
        let cd=(index,obj,replace)=>{
            let tar=obj.children[index];
            if(replace)obj.children[index]=NULL;
            return tar;
        };
        let temp=object;
        for(let n=0;n<name.length;n++){
            let i=name[n];
            temp=cd(i,temp,n===name.length-1);
        }
        if(!temp)console.warn('no child was found!');
        return temp;
    }

    /**
     * 获取object中名为name的对象
     * @param name {String} 对象的name属性值
     * @param object {Object3D} 要查询的对象
     * @param type {string} 查询类型(即name键所在目录)：{none：对象的名称object.name}，{material：材质的名称object.material.name},{userData：用户数据名称object.userData.name}
     * @returns {Array} 自上而下的索引序列
     */
    static search(name,object,type='none'){
        return Child._searchInternal(name,object,type);
    }

    /**
     * 内部查询方法
     * @param strName 查询字符串
     * @param object 查询对象
     * @param type 查询类型
     * @param indices 输入的已有结果
     * @param t 输出的最终结果
     * @returns {Array}
     * @private
     */
    static _searchInternal(strName,object,type,indices=[],t=[]){
        for(let i=0;i<object.children.length;i++){
            let c=object.children[i];
            let sus=false;
            switch (type) {
                case 'none':
                    if(c.name!==undefined)sus=c.name===strName;
                    break;
                case 'material':
                    if(c.material!==undefined&&c.material.name!==undefined)sus=c.material.name===strName;
                    break;
                case 'userData':
                    if(c.userData!==undefined&&c.userData.name!==undefined)sus=c.userData.name===strName;
                    break;
            }
            if(sus){
                t.push(...indices,i);
                return t;
            }else{
                let ts=Child._searchInternal(strName,c,type,[...indices,i],t);
                if(ts.length>0){
                    return ts;
                }
            }
        }
        return t;
    }
}